package com.codeanalysissys.backend.service.frame.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codeanalysissys.backend.controller.FileController;
import com.codeanalysissys.backend.cpp.CppASTBuilder;
import com.codeanalysissys.backend.cpp.CppCFGBuilder;
import com.codeanalysissys.backend.cpp.CppDDGBuilder;
import com.codeanalysissys.backend.entity.DTO.AnalysisResultDTO;
import com.codeanalysissys.backend.entity.Language;
import com.codeanalysissys.backend.entity.UploadFile;
import com.codeanalysissys.backend.entity.response.ResponseCode;
import com.codeanalysissys.backend.entity.response.Result;
import com.codeanalysissys.backend.entity.task.JSONLAnalysisTask;
import com.codeanalysissys.backend.golang.GoASTBuilder;
import com.codeanalysissys.backend.golang.GoCDGBuilder;
import com.codeanalysissys.backend.golang.GoCFGBuilder;
import com.codeanalysissys.backend.golang.GoDDGBuilder;
import com.codeanalysissys.backend.graphs.ast.ASEdge;
import com.codeanalysissys.backend.graphs.ast.ASNode;
import com.codeanalysissys.backend.graphs.ast.AbstractSyntaxTree;
import com.codeanalysissys.backend.graphs.cfg.CFEdge;
import com.codeanalysissys.backend.graphs.cfg.CFNode;
import com.codeanalysissys.backend.graphs.cfg.ControlFlowGraph;
import com.codeanalysissys.backend.graphs.pdg.*;
import com.codeanalysissys.backend.java.JavaASTBuilder;
import com.codeanalysissys.backend.java.JavaCDGBuilder;
import com.codeanalysissys.backend.java.JavaCFGBuilder;
import com.codeanalysissys.backend.java.JavaDDGBuilder;
import com.codeanalysissys.backend.javascript.JavaScriptASTBuilder;
import com.codeanalysissys.backend.javascript.JavaScriptCDGBuilder;
import com.codeanalysissys.backend.javascript.JavaScriptCFGBuilder;
import com.codeanalysissys.backend.javascript.JavaScriptDDGBuilder;
import com.codeanalysissys.backend.python.PythonASTBuilder;
import com.codeanalysissys.backend.python.PythonCDGBuilder;
import com.codeanalysissys.backend.python.PythonCFGBuilder;
import com.codeanalysissys.backend.python.PythonDDGBuilder;
import com.codeanalysissys.backend.ruby.RubyASTBuilder;
import com.codeanalysissys.backend.ruby.RubyCDGBuilder;
import com.codeanalysissys.backend.ruby.RubyCFGBuilder;
import com.codeanalysissys.backend.ruby.RubyDDGBuilder;
import com.codeanalysissys.backend.service.frame.FileService;
import com.codeanalysissys.backend.utils.CodeAnalysisUtils;
import com.codeanalysissys.backend.utils.CookieUtil;
import com.codeanalysissys.backend.utils.RedisCache;
import ghaffarian.graphs.Edge;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class FileServiceImpl implements FileService {
    public final static int ANALYSE_FAIL = -1;
    public final static int ANALYSE_NO = 0;
    public final static int ANALYSE_ING = 1;
    public final static int ANALYSE_SUCCESS = 2;

    @Autowired
    private CookieUtil cookieUtil;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private CodeAnalysisUtils codeAnalysisUtils;

    @Value("${upload-file.src-dir}")
    private String srcDir;

    @Value("${upload-file.output-dir}")
    private String outputDir;

    // 单线程线程池，用于处理单一语言源代码文件分析
    private ExecutorService singleThreadPool;

    // 固定大小线程池，用于处理 JSONL 数据集文件分析，线程数为 CPU 核心数 * 2
    private ExecutorService fixedThreadPool;

    @PostConstruct
    public void init() {
        // 初始化线程池
        this.singleThreadPool = Executors.newSingleThreadExecutor();
        // 获取系统CPU核心数
        int cores = Runtime.getRuntime().availableProcessors();
        // 创建固定大小的线程池，线程数为CPU核心数*2
        fixedThreadPool = Executors.newFixedThreadPool(cores * 2);
    }

    /**
     * 上传文件并进行分析
     *
     * @param type
     * @param lang
     * @param name
     * @param desc
     * @param file
     * @param multiThread
     * @return
     */
    @Override
    public Result analysisFile(int type, Language lang, String name, String desc, MultipartFile file, Boolean multiThread) {
        // 随机生成 fileId
        String fileId = cookieUtil.generateUUID();

        // 将文件保存到本地
        // 创建目标文件夹 srcDir/fileId
        File targetFolder = new File(srcDir, fileId);
        if (!targetFolder.exists()) {
            targetFolder.mkdirs();
        }
        log.info("正在处理文件：{}", file.getOriginalFilename());
        // 保存文件到目标文件夹
        File targetFile = new File(targetFolder, Objects.requireNonNull(file.getOriginalFilename()));

        // 将文件写入本地
        try {
            targetFile.createNewFile();
            file.transferTo(targetFile);
        } catch (IOException ioException) {
            // 若出现io异常就返回失败信息
            log.error("文件上传失败", ioException);
            return new Result.Builder(ResponseCode.UPLOAD_FAIL).build();
        }

        // 获取文件路径
        String filePath = targetFile.getAbsolutePath();

        // 创建 UploadFile 对象并存入 Redis 并设置有效期 1 天
        UploadFile uploadFile = new UploadFile.Builder(fileId, type, filePath, file.getOriginalFilename()).setName(name).setDesc(desc).setState(ANALYSE_ING).setGraphPath(targetFolder.getAbsolutePath()).build();
        redisCache.setCacheObject(fileId, uploadFile, 1, TimeUnit.DAYS);

        // 根据 type 类型新开线程进行分析
        new Thread(() -> {
            if (type == UploadFile.SINGLE) {
                // 单一语言源代码的分析方法
                uploadFile.setLanguage(lang);
                // 提交任务到单线程线程池
                singleThreadPool.submit(() -> codeAnalysisUtils.analyseSingle(uploadFile));
            } else if (type == UploadFile.JSONL && multiThread) {
                // JSONL 数据集的分析方法且为多线程
                // 提交任务到固定大小线程池
                fixedThreadPool.submit(() -> codeAnalysisUtils.analyseJsonlV2(uploadFile));
            } else {
                // JSONL 数据集的分析方法且为单线程
                // 提交任务到固定大小线程池
                fixedThreadPool.submit(() -> codeAnalysisUtils.analyseJsonlV1(uploadFile));
            }
        }).start();

        return new Result.Builder(ResponseCode.UPLOAD_SUCCESS).data(fileId).build();
    }

    @Override
    public Result getAnalysisResult(String fileId) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 将 JSON 字符串解析为 UploadFile 对象
            UploadFile uploadFile = objectMapper.readValue(redisCache.getCacheObject(fileId).toString(), UploadFile.class);
            AnalysisResultDTO analysisResultDTO = uploadFile.toAnalysisResultDTO();
            return new Result.Builder(ResponseCode.GET_SUCCESS).data(analysisResultDTO).build();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
//        if (uploadFile.getState() == ANALYSE_SUCCESS) {
//            // todo 获取该文件的系统性信息
//            return new Result.Builder(ResponseCode.UPLOAD_SUCCESS).data(uploadFile.toAnalysisResultDTO()).build();
//        }
//        return new Result.Builder(ResponseCode.UPLOAD_SUCCESS).data(uploadFile.toAnalysisResultDTO()).build();
    }

    @Override
    public String getSingleGraphRes(String fileId, String format) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 获取缓存中的JSON字符串，并解析为UploadFile对象
            UploadFile uploadFile = objectMapper.readValue(redisCache.getCacheObject(fileId).toString(), UploadFile.class);
            return codeAnalysisUtils.getZipRes(uploadFile, format);
        } catch (Exception e) {
            // 若异常就返回失败信息
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String getSingleDataRes(String fileId) {
        return null;
    }

    @Override
    public String getJSONLRes(String fileId, Integer exportType) {
        ObjectMapper objectMapper = new ObjectMapper();
        String filePath = null;
        try {
            // 获取缓存中的JSON字符串，并解析为UploadFile对象
            UploadFile uploadFile = objectMapper.readValue(redisCache.getCacheObject(fileId).toString(), UploadFile.class);
            filePath = Objects.equals(exportType, FileController.JSONL_GRAPH_RES) ? uploadFile.getGraphPath() : uploadFile.getDataPath();
        } catch (Exception e) {
            return null;
        }
        return filePath;
    }


    // 以下为测试方法
    @Override
    public long testMultiThreads(String filePath, int threadCount) {
        // 创建固定线程数的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        // 获取 jsonl 的文件路径,然后再重新写回文件
        File file = new File(filePath);
        String outDir = file.getParent();
        if (!file.exists()) {
            log.error("文件不存在");
            return -1;
        }

        // 拼接输出文件的路径，输出文件文件名为：源文件名 + "_result.jsonl"
        String outFilePath = outDir + System.getProperty("file.separator") + file.getName().split("\\.")[0] + "_result.jsonl";
        // 创建输出文件
        File outFile = new File(outFilePath);

        // 记录以下代码开始执行的时间戳
        long start = System.currentTimeMillis();

        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(outFile))) {

            String line;
            int lineNum = 0;

            // 逐行读取文件并提交解析任务到线程池
            while ((line = bufferedReader.readLine()) != null) {
                lineNum++;
                // 创建解析任务并提交到线程池
                Runnable task = new JSONLAnalysisTask(line, lineNum, file.getName(), bufferedWriter);
                executorService.submit(task);
            }

        } catch (Exception e) {
            log.error("读取文件异常");
            return -1;
        }

        // 关闭线程池，不再接受新任务
        executorService.shutdown();

        try {
            // 等待所有任务执行完成，设置超时时间为1天
            if (!executorService.awaitTermination(1, TimeUnit.DAYS)) {
                log.error("等待超时");
            }
        } catch (InterruptedException e) {
            log.error("等待被中断");
        }

        // 记录以下代码执行结束的时间戳
        long end = System.currentTimeMillis();

        return end - start;
    }

    // 测试单线程执行
    @Override
    public long testSingleThread(String filePath) {
        // 获取 jsonl 的文件路径,然后再重新写回文件
        File file = new File(filePath);
        String outDir = file.getParent();
        if (!file.exists()) {
            log.error("文件不存在");
            return -1;
        }
        // 拼接输出文件的路径，输出文件文件名为：源文件名 + "_result.jsonl"
        String outFilePath = outDir + System.getProperty("file.separator") + file.getName().split("\\.")[0] + "_result.jsonl";
        // 创建输出文件
        File outFile = new File(outFilePath);

        // 记录以下代码开始执行的时间戳
        long start = System.currentTimeMillis();

        // 分别记录 CFG,CDG,DDG,AST
        Map<String, Set<String>> map1 = new HashMap<>(256);
        Map<String, Set<String>> map2 = new HashMap<>(256);
        Map<String, Set<String>> map3 = new HashMap<>(256);
        Map<String, Set<String>> map4 = new HashMap<>(256);

        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(outFile))) {
            DecimalFormat formatter = new DecimalFormat("##.##%");
            String line;
            int lineNum = 0;

            while ((line = bufferedReader.readLine()) != null) {
                // 读取行号自增 1
                lineNum = lineNum + 1;

                // 提取行内信息，包括路径、类名和语言
                JSONObject jsonObj = JSON.parseObject(line);
                String path = jsonObj.getString("path");
                String className = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
                String selectLanguage = jsonObj.getString("language");

                // 根据语言选择对应的解析器
                switch (selectLanguage) {
                    case "java" -> {
                        // 执行与 Java 相关的代码,首先为 csn 代码加上对应的类名
                        String code = "class " + className + " {\n" + jsonObj.getString("code") + "\n}";
                        try {
                            try {
                                // 解析 CFG
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlFlowGraph cfg = JavaCFGBuilder.build(codeStream);
                                // 打包 CFG
                                packCFG(map1, jsonObj, cfg);
                            } catch (Throwable ex) {
                            }
                            try {
                                // 解析 DDG
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                DataDependenceGraph ddg = JavaDDGBuilder.build(codeStream);
                                // 打包 DDG
                                packDDG(map3, jsonObj, ddg);
                            } catch (Throwable ex) {
                            }
                            try {
                                // 解析 CDG
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlDependenceGraph cdg = JavaCDGBuilder.build(codeStream);
                                // 打包 CDG
                                packCDG(map2, jsonObj, cdg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                AbstractSyntaxTree ast = JavaASTBuilder.build(codeStream);
                                // 打包AST
                                packAST(map4, jsonObj, ast);
                            } catch (Throwable ex) {
                            }
                            bufferedWriter.write(jsonObj.toJSONString());
                            bufferedWriter.newLine();
                        } catch (Throwable ex) {
                            System.out.println(ex.getMessage());
                        } finally {
                            map1.clear();
                            map2.clear();
                            map3.clear();
                            map4.clear();

                        }
                    }

                    case "python" -> {
                        // 执行与Python相关的代码,首先为csn代码加上对应的类名
                        String code = jsonObj.getString("code");
                        try {
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlFlowGraph cfg = PythonCFGBuilder.build(codeStream);
                                // 打包CFG
                                packCFG(map1, jsonObj, cfg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes2 = code.getBytes();
                                InputStream codeStream2 = new ByteArrayInputStream(bytes2);
                                DataDependenceGraph ddg = PythonDDGBuilder.build(codeStream2);
                                // 打包DDG
                                packDDG(map3, jsonObj, ddg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlDependenceGraph cdg = PythonCDGBuilder.build(codeStream);
                                // 打包CDG
                                packCDG(map2, jsonObj, cdg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                AbstractSyntaxTree ast = PythonASTBuilder.build(codeStream);
                                // 打包AST
                                packAST(map4, jsonObj, ast);
                            } catch (Throwable ex) {
                            }
                            bufferedWriter.write(jsonObj.toJSONString());
                            bufferedWriter.newLine();
                        } catch (Throwable ex) {
                            System.out.println("文件：" + file.getName() + "行数：" + lineNum);
                        } finally {
                            map1.clear();
                            map2.clear();
                            map3.clear();
                            map4.clear();

                        }
                    }

                    case "go" -> {
                        // 执行与Java相关的代码,首先为csn代码加上对应的类名
                        String code = jsonObj.getString("code");
                        try {
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlFlowGraph cfg = GoCFGBuilder.build(codeStream);
                                // 打包CFG
                                packCFG(map1, jsonObj, cfg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes2 = code.getBytes();
                                InputStream codeStream2 = new ByteArrayInputStream(bytes2);
                                DataDependenceGraph ddg = GoDDGBuilder.build(codeStream2);
                                // 打包DDG
                                packDDG(map3, jsonObj, ddg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlDependenceGraph cdg = GoCDGBuilder.build(codeStream);
                                // 打包CDG
                                packCDG(map2, jsonObj, cdg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                AbstractSyntaxTree ast = GoASTBuilder.build(codeStream);
                                // 打包AST
                                packAST(map4, jsonObj, ast);
                            } catch (Throwable ex) {
                            }
                            bufferedWriter.write(jsonObj.toJSONString());
                            bufferedWriter.newLine();
                        } catch (Throwable ex) {
                            System.out.println("文件：" + file.getName() + "行数：" + lineNum);
                        } finally {
                            map1.clear();
                            map2.clear();
                            map3.clear();
                            map4.clear();

                        }
                    }

                    case "ruby" -> {
                        // 执行与Java相关的代码,首先为csn代码加上对应的类名
                        String code = jsonObj.getString("code");
                        try {
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlFlowGraph cfg = RubyCFGBuilder.build(codeStream);
                                // 打包CFG
                                packCFG(map1, jsonObj, cfg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes2 = code.getBytes();
                                InputStream codeStream2 = new ByteArrayInputStream(bytes2);
                                DataDependenceGraph ddg = RubyDDGBuilder.build(codeStream2);
                                // 打包DDG
                                packDDG(map3, jsonObj, ddg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlDependenceGraph cdg = RubyCDGBuilder.build(codeStream);
                                // 打包CDG
                                packCDG(map2, jsonObj, cdg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                AbstractSyntaxTree ast = RubyASTBuilder.build(codeStream);
                                // 打包AST
                                packAST(map4, jsonObj, ast);
                            } catch (Throwable ex) {
                            }
                            bufferedWriter.write(jsonObj.toJSONString());
                            bufferedWriter.newLine();
                        } catch (Throwable ex) {
                            System.out.println("文件：" + file.getName() + "行数：" + lineNum);
                        } finally {
                            map1.clear();
                            map2.clear();
                            map3.clear();
                            map4.clear();

                        }
                    }

                    case "javascript" -> {
                        // 执行与JavaScript相关的代码
                        String code = jsonObj.getString("code");
                        try {
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlFlowGraph cfg = JavaScriptCFGBuilder.build(codeStream);
                                // 打包CFG
                                packCFG(map1, jsonObj, cfg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes2 = code.getBytes();
                                InputStream codeStream2 = new ByteArrayInputStream(bytes2);
                                DataDependenceGraph ddg = JavaScriptDDGBuilder.build(codeStream2);
                                // 打包DDG
                                packDDG(map3, jsonObj, ddg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlDependenceGraph cdg = JavaScriptCDGBuilder.build(codeStream);
                                // 打包CDG
                                packCDG(map2, jsonObj, cdg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                AbstractSyntaxTree ast = JavaScriptASTBuilder.build(codeStream);
                                // 打包AST
                                packAST(map4, jsonObj, ast);
                            } catch (Throwable ex) {
                            }
                            bufferedWriter.write(jsonObj.toJSONString());
                            bufferedWriter.newLine();
                        } catch (Throwable ex) {
                            System.out.println("文件：" + file.getName() + "行数：" + lineNum);
                        } finally {
                            map1.clear();
                            map2.clear();
                            map3.clear();
                            map4.clear();

                        }
                    }

                    case "c++" -> {
                        // 执行与C++相关的代码
                        String code = jsonObj.getString("code");
                        try {
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                ControlFlowGraph cfg = CppCFGBuilder.build(codeStream);
                                // 打包CFG
                                packCFG(map1, jsonObj, cfg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes2 = code.getBytes();
                                InputStream codeStream2 = new ByteArrayInputStream(bytes2);
                                DataDependenceGraph ddg = CppDDGBuilder.build(codeStream2);
                                // 打包DDG
                                packDDG(map3, jsonObj, ddg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
//                                    ControlDependenceGraph cdg = CppCDGBuilder.build(codeStream);
                                ControlDependenceGraph cdg = null;
                                // 打包CDG
                                packCDG(map2, jsonObj, cdg);
                            } catch (Throwable ex) {
                            }
                            try {
                                byte[] bytes = code.getBytes();
                                InputStream codeStream = new ByteArrayInputStream(bytes);
                                AbstractSyntaxTree ast = CppASTBuilder.build(codeStream);
                                // 打包AST
                                packAST(map4, jsonObj, ast);
                            } catch (Throwable ex) {
                            }
                            bufferedWriter.write(jsonObj.toJSONString());
                            bufferedWriter.newLine();
                        } catch (Throwable ex) {
                            System.out.println("文件：" + file.getName() + "行数：" + lineNum);
                        } finally {
                            map1.clear();
                            map2.clear();
                            map3.clear();
                            map4.clear();

                        }
                    }

                    // 如果没有匹配的情况，执行默认的代码块
                    default -> System.out.println("Unsupported programming language.");

                }
            }
            try {
                bufferedWriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 记录以下代码执行结束的时间戳
        long end = System.currentTimeMillis();

        return end - start;
    }

    private void packCDG(Map<String, Set<String>> map2, JSONObject jsonObj, ControlDependenceGraph cdg) {
        Iterator<Edge<PDNode, CDEdge>> it = cdg.allEdgesIterator();
        while (it.hasNext()) {
            Edge<PDNode, CDEdge> edge = it.next();
            wrapToMap(map2, edge.source.getCode(), edge.target.getCode());
        }
        jsonObj.put("control_dependency", map2);
    }

    private void packAST(Map<String, Set<String>> map4, JSONObject jsonObj, AbstractSyntaxTree ast) {
        Iterator<Edge<ASNode, ASEdge>> it = ast.allEdgesIterator();
        while (it.hasNext()) {
            Edge<ASNode, ASEdge> edge = it.next();
            wrapToMap(map4, edge.source, edge.target);
//            wrapToMap(map4, edge.source.getCode(), edge.target.getCode());
        }
        jsonObj.put("AST_Edge", map4);
    }

    private void packDDG(Map<String, Set<String>> map3, JSONObject jsonObj, DataDependenceGraph ddg) {
        Iterator<Edge<PDNode, DDEdge>> it = ddg.allEdgesIterator();
        while (it.hasNext()) {
            Edge<PDNode, DDEdge> edge = it.next();
            wrapToMap(map3, edge.source.getCode(), edge.target.getCode());
        }
        jsonObj.put("data_dependency", map3);
    }

    private void packCFG(Map<String, Set<String>> map1, JSONObject jsonObj, ControlFlowGraph cfg) {
        Iterator<Edge<CFNode, CFEdge>> it = cfg.allEdgesIterator();
        while (it.hasNext()) {
            Edge<CFNode, CFEdge> edge = it.next();
            wrapToMap(map1, edge.source.getCode(), edge.target.getCode());
        }
        jsonObj.put("cfg_dependency", map1);
    }

    private static void wrapToMap(Map<String, Set<String>> map, String code2, String code3) {
        if (map.get(code2) == null) {
            Set<String> set = new HashSet<>();
            set.add(code3);
            map.put(code2, set);
        } else {
            map.get(code2).add(code3);
        }
    }

    // To deal with the AST Node
    private static void wrapToMap(Map<String, Set<String>> map, ASNode srcNode, ASNode tarNode) {
        String srcContent = (srcNode.getCode() == null || srcNode.getCode() == "") ? srcNode.getProperty("type").toString() : srcNode.getCode();
        String tarContent = (tarNode.getCode() == null || tarNode.getCode() == "") ? tarNode.getProperty("type").toString() : tarNode.getCode();
        srcContent = srcNode.getId() + ":" + srcContent;
        tarContent = tarNode.getId() + ":" + tarContent;
        if (map.get(srcContent) == null) {
            Set<String> set = new HashSet<>();
            set.add(tarContent);
            map.put(srcContent, set);
        } else {
            map.get(srcContent).add(tarContent);
        }
    }
}
